﻿using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
using Evaluant.Uss.DomainModel.ClassModel;
using System.CodeDom.Compiler;

namespace DbReverseGeneratorTest
{
    [TestFixture]
    public class DomainCodeGeneratorTest
    {
        #region Ctor
        public DomainCodeGeneratorTest()
        {
        } 
        #endregion

        #region Model

        protected virtual Model GetModel()
        {
            Model model = new Model();
            model.Package = new Package("TestOrders");

            Class order = new Class("Order");
            model.Package.Classes.Add(order);
            order.Properties.Add(new Property("Number", "System.Int32"));
            order.Properties.Add(new Property("Customer", "System.String"));
            order.Properties.Add(new Property("Date", "System.DateTime"));

            Class product = new Class("Product");
            model.Package.Classes.Add(product);
            product.Properties.Add(new Property("Id", "System.String"));
            product.Properties.Add(new Property("Name", "System.String"));
            product.Properties.Add(new Property("Desc", "System.String"));
            product.Properties.Add(new Property("Price", "System.Single"));

            Relationship refProducts = new Relationship("Product");
            model.Package.Relationships.Add(refProducts);
            refProducts.Parent = new Parent("Order", "1", "Order");
            refProducts.Child = new Child("Product", "*", "Products");

            return model;
        }

        #endregion

        #region Utils

        protected virtual CompilerResults CompileCSharpCode(string[] files)
        {
            return CompileCode(files, new Microsoft.CSharp.CSharpCodeProvider());
        }

        protected virtual CompilerResults CompileVBCode(string[] files)
        {
            return CompileCode(files, new Microsoft.VisualBasic.VBCodeProvider());
        }

        protected virtual CompilerResults CompileCode(string[] files, CodeDomProvider compiler)
        {
            CompilerParameters compParams = new CompilerParameters();
            compParams.GenerateInMemory = true;
            compParams.ReferencedAssemblies.AddRange(new string[]{"System.dll"});

            return compiler.CompileAssemblyFromFile(compParams, files);
        }

        #endregion

        [Test]
        public void CodeCSSingleFileGenerator()
        {
            DomainCodeGenerator.DomainCodeGenerator codeGen = new DomainCodeGenerator.DomainCodeGenerator();
            codeGen.DomainModel = GetModel();
            codeGen.Language = DomainCodeGenerator.DomainCodeGenerator.CodeLanguage.CSharp;
            codeGen.Options = DomainCodeGenerator.DomainCodeGenerator.GenerationOptions.SingleCodeFile;

            codeGen.GenerateSourceCode();

            foreach (string f in codeGen.GeneratedFiles)
            {
                Console.WriteLine(f);
            }

            CompilerResults results = CompileCSharpCode(codeGen.GeneratedFiles);
            foreach (CompilerError ce in results.Errors)
            {
                Console.WriteLine(ce.ToString());
            }
            Assert.IsFalse(results.Errors.HasErrors);
        }

        [Test]
        public void CodeCSMultipleFileGenerator()
        {
            DomainCodeGenerator.DomainCodeGenerator codeGen = new DomainCodeGenerator.DomainCodeGenerator();
            codeGen.DomainModel = GetModel();
            codeGen.Language = DomainCodeGenerator.DomainCodeGenerator.CodeLanguage.CSharp;
            codeGen.Options = DomainCodeGenerator.DomainCodeGenerator.GenerationOptions.MultipleCodeFiles;

            codeGen.GenerateSourceCode();

            foreach (string f in codeGen.GeneratedFiles)
            {
                Console.WriteLine(f);
            }

            CompilerResults results = CompileCSharpCode(codeGen.GeneratedFiles);
            foreach (CompilerError ce in results.Errors)
            {
                Console.WriteLine(ce.ToString());
            }
            Assert.IsFalse(results.Errors.HasErrors);
        }


        [Test]
        public void CodeVBSingleFileGenerator()
        {
            DomainCodeGenerator.DomainCodeGenerator codeGen = new DomainCodeGenerator.DomainCodeGenerator();
            codeGen.DomainModel = GetModel();
            codeGen.Language = DomainCodeGenerator.DomainCodeGenerator.CodeLanguage.VisualBasic;
            codeGen.Options = DomainCodeGenerator.DomainCodeGenerator.GenerationOptions.SingleCodeFile;

            codeGen.GenerateSourceCode();

            foreach (string f in codeGen.GeneratedFiles)
            {
                Console.WriteLine(f);
            }

            CompilerResults results = CompileCSharpCode(codeGen.GeneratedFiles);
            
            foreach(CompilerError ce in results.Errors)
            {
                Console.WriteLine(ce.ToString());
            }
            Assert.IsFalse(results.Errors.HasErrors);
        }
    }
}
